package alchemist.dao.local;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import alchemist.model.Combination;
import alchemist.model.Element;

public class DataCache
{
    private Map< String, Element >                         elements      = new HashMap< String, Element >();
    private Map< Element, Map< Element, Set< Element > > > combinations  = new HashMap< Element, Map< Element, Set< Element > > >();
    private Set< Element >                                 basicElements = new HashSet< Element >();                                 ;

    public Element get( String id )
    {
        return this.elements.get( id );
    }

    public void put( Element element )
    {
        this.elements.put( element.getId(), element );
    }
    
    public Set< Element > get( Combination combination )
    {
        Set< Element > result = new HashSet< Element >();
        final Map< Element, Set< Element > > combinableWith = this.combinations.get( elements.get( combination.getFirst() ) );
        if ( combinableWith != null && combinableWith.containsKey( elements.get( combination.getSecond() ) ) )
        {
            result = combinableWith.get( elements.get( combination.getSecond() ) );
        }
        return result;
    }

    public void put( Combination combination, Set< Element > elements )
    {
        final Element first = this.elements.get( combination.getFirst() );
        final Element second = this.elements.get( combination.getSecond() );
        addCombination( elements, first, second );
        addCombination( elements, second, first );
    }

    private void addCombination( Set< Element > elements, final Element first, final Element second )
    {
        if ( this.combinations.containsKey( first ) )
        {
            this.combinations.get( first ).put( second, elements );
        }
        else
        {
            this.combinations.put( first, createCombination( second.getId(), elements ) );
        }
    }

    private Map< Element, Set< Element > > createCombination( String elementId, Set< Element > elements )
    {
        final Map< Element, Set< Element > > result = new HashMap< Element, Set< Element > >();
        result.put( this.elements.get( elementId ), elements );
        return result;
    }

    public Map< String, Element > getElements()
    {
        return Collections.unmodifiableMap( this.elements );
    }

    public void addBasic( Element element )
    {
        this.basicElements.add( element );
    }

    public Set< Element > getBasicElements()
    {
        return Collections.unmodifiableSet( this.basicElements );
    }
}
